/*
 * Copyright 1999-2018 Alibaba Group Holding Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.wxapp.common.util.string;

import com.alibaba.nacos.common.utils.ArrayUtils;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.wxapp.common.constant.constant.PatternConstant;
import com.wxapp.common.util.check.CheckUtil;

import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class StringUtil {
    private static final int INDEX_NOT_FOUND = -1;

    private static final String[] EMPTY_STRING_ARRAY = {};
    private StringUtil() {
    }
    /** 下划线转驼峰 */
    public static String lineToHump(String str) {
        Pattern linePattern = Pattern.compile("_(\\w)");
        str = str.toLowerCase();
        Matcher matcher = linePattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /** 驼峰转下划线,效率比上面高 */
    public static String humpToLine(String str) {
        Pattern humpPattern = Pattern.compile("[A-Z]");
        Matcher matcher = humpPattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * 创建一个编码格式为 utf8 的字符串
     */
    public static String newStringForUtf8(byte[] bytes) {
        return new String(bytes, StandardCharsets.UTF_8);
    }

    /**
     * 比较两个 CharSequences，如果它们表示相等的字符序列，则返回 true 。
     */
    public static boolean equals(String str1, String str2) {
        return Objects.equals(str1, str2);
    }

     /**
     * 从此 String 的两端删除控制字符 （char <= 32）， null 通过返回 null
     */
    public static String trim(final String str) {
        return str == null ? null : str.trim();
    }

    /**
     * 两个索引之间的子字符串
     */
    public static String substringBetween(String str, String open, String close) {
        if (str == null || open == null || close == null) {
            return null;
        }
        int start = str.indexOf(open);
        if (start != INDEX_NOT_FOUND) {
            int end = str.indexOf(close, start + open.length());
            if (end != INDEX_NOT_FOUND) {
                return str.substring(start + open.length(), end);
            }
        }
        return null;
    }

    /**
     * 将所提供数组的元素联接到包含提供的元素列表的单个 String 中
     */
    public static String join(Collection collection, String separator) {
        if (collection == null) {
            return null;
        }

        StringBuilder stringBuilder = new StringBuilder();
        Object[] objects = collection.toArray();

        for (int i = 0; i < collection.size(); i++) {
            if (objects[i] != null) {
                stringBuilder.append(objects[i]);
                if (i != collection.size() - 1 && separator != null) {
                    stringBuilder.append(separator);
                }
            }
        }

        return stringBuilder.toString();
    }

    /**
     *检查 CharSequence 是否包含搜索 CharSequence，而不考虑大小写、处理 null。不区分大小写定义为 String.equalsIgnoreCase(String)。
     * CharSequence null 将返回 false
     */
    public static boolean containsIgnoreCase(final CharSequence str, final CharSequence searchStr) {
        if (str == null || searchStr == null) {
            return false;
        }
        String str1 = str.toString().toLowerCase();
        String str2 = searchStr.toString().toLowerCase();
        return str1.contains(str2);
    }

    /**
     * 检查 CharSequence 是否包含搜索 CharSequence
     */
    public static boolean contains(final CharSequence str, final CharSequence searchStr) {
        if (str == null || searchStr == null) {
            return false;
        }
        return str.toString().contains(searchStr);
    }

    /**
     * 检查 CharSequence 是否以指定的前缀开头。
     * nulls 的处理没有例外。两个 null 引用被认为是相等的。比较区分大小写
     */
    public static boolean startsWith(final CharSequence str, final CharSequence prefix) {
        return startsWith(str, prefix, false);
    }

    /**
     * 检查 CharSequence 是否以指定的前缀开头（可选，不区分大小写）
     */
    private static boolean startsWith(final CharSequence str, final CharSequence prefix, final boolean ignoreCase) {
        if (str == null || prefix == null) {
            return str == null && prefix == null;
        }
        if (prefix.length() > str.length()) {
            return false;
        }
        if (ignoreCase) {
            String lowerCaseStr = str.toString().toLowerCase();
            String lowerCasePrefix = prefix.toString().toLowerCase();
            return lowerCaseStr.startsWith(lowerCasePrefix);
        } else {
            return str.toString().startsWith(prefix.toString());
        }
    }

    /**
     *不区分大小写检查 CharSequence 是否以指定的前缀开头。
     * nulls 的处理没有例外。两个 null 引用被认为是相等的。比较不区分大小写
     */
    public static boolean startsWithIgnoreCase(final CharSequence str, final CharSequence prefix) {
        return startsWith(str, prefix, true);
    }

    /**
     * 从 String 中删除所有 Character.isWhitespace(char)空格，如 所定义
     */
    public static String deleteWhitespace(String str) {
        if (CheckUtil.isNullString(str)) {
            return str;
        }
        int sz = str.length();
        char[] chs = new char[sz];
        int count = 0;
        for (int i = 0; i < sz; i++) {
            if (!Character.isWhitespace(str.charAt(i))) {
                chs[count++] = str.charAt(i);
            }
        }
        if (count == sz) {
            return str;
        }
        return new String(chs, 0, count);
    }

    /**
     * 比较两个 CharSequence，如果它们表示相等的字符序列，则返回 true ，忽略大小写
     */
    public static boolean equalsIgnoreCase(String str1, String str2) {
        return str1 == null ? str2 == null : str1.equalsIgnoreCase(str2);
    }


    /**
     * 将给定的复制到 Collection 数组 String 中
     */
    public static String[] toStringArray(Collection<String> collection) {
        return (!CollectionUtils.isEmpty(collection) ? collection.toArray(EMPTY_STRING_ARRAY) : EMPTY_STRING_ARRAY);
    }

    /**
     * Check whether the given {@code String} contains actual <em>text</em>.
     *
     * <p>More specifically, this method returns {@code true} if the
     * {@code String} is not {@code null}, its length is greater than 0, and it contains at least one non-whitespace
     * character.
     *
     * @param str the {@code String} to check (maybe {@code null})
     * @return {@code true} if the {@code String} is not {@code null}, its length is greater than 0, and it does not
     * contain whitespace only
     * @see Character#isWhitespace
     */
    public static boolean hasText(String str) {
        return (str != null && !str.isEmpty() && containsText(str));
    }

    /**
     * 判断是否为空格
     * @param str
     * @return
     */
    private static boolean containsText(CharSequence str) {
        int strLen = str.length();
        for (int i = 0; i < strLen; i++) {
            if (!Character.isWhitespace(str.charAt(i))) {
                return true;
            }
        }
        return false;
    }

    public static Boolean isPhone(String phone) {
        return Pattern.matches(PatternConstant.PHONE_PATTERN, phone);
    }

    /**
     *  是否是邮箱
     */
    public static Boolean isEmail(String email) {
        return Pattern.matches(PatternConstant.EMAIL_PATTERN, email);
    }

    /**
     * @desc: 是否是身份证
     */
    public static Boolean isIdCard(String idCard) {
        return Pattern.matches(PatternConstant.IDCARD_PATTERN, idCard);
    }


}
